#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
typedef int           /* 1 в случае ошибки, 0 в прот. случае */
(*PFUNC)(const char*, const struct stat*);

int             /* 1 в случае ошибки, 0 в прот. случае */
walk(const char*,       /* начальная директория */
     PFUNC, int);       /* функция, которая вызывается для каждого элемента директории */


int print_entry(const char* name, const struct stat* st)

{
    printf("%s%s\n", name);
    return 0;
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
    fprintf(stderr, "Usage: %s DIR\n", argv[0]);
    exit(1);
    }

    exit(walk(argv[1], print_entry, 1));
}

char buf[PATH_MAX];

int walk(const char* dirname, PFUNC pfunc, int do_dirs)

{
    DIR* dp;
    struct stat st;
    struct dirent* dirp;
    int retval = 0;

    size_t len = strlen(dirname);

    if((dp = opendir(dirname)) == NULL) {
        perror(dirname);
        return 1;
    }

    strncpy(buf, dirname, len);

    while((dirp = readdir(dp)) != NULL) {
        if(strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
        continue;

        buf[len] = '/';
        buf[len+1] = '\0';

        strcat(buf, dirp->d_name);

        if(lstat(buf, &st) == -1) {
            perror(dirp->d_name);
            retval = 1;
            break;
        }

        if(S_ISDIR(st.st_mode)) {
            if(do_dirs) {
                if(pfunc(buf, &st) == 1){
                    retval = 1;
                    break;
                }
            }

            if(walk(buf, pfunc, do_dirs) == 1) {
                retval = 1;
                break;
            }
        }

    else if(pfunc(dirp->d_name, &st) == 1) {
        retval = 1;
        break;
    }

    buf[len] = '\0';
    }

    closedir(dp);
    return retval;
}
